﻿using System;
using SoundLibrary.Converter;

namespace SoundLibrary.BeatDetection
{
    public class BeatDetector
    {
        float[] averageEnergy;
        float totalEnergy;
        float lastEnergyValue;
        float currentEnergy;
        int[] beginFrequency;
        int[] endFrequency;
        const float noiseOffset = 2.0f;
        int total;
        int begin;
        private bool beat;

        public bool Beat
        {
            get { return beat; }
        }

        public BeatDetector(int begin, int end)
        {
            float initialValue = 1.0f;

            this.beginFrequency = new int[2];
            this.endFrequency = new int[2];

            this.beginFrequency[0] = begin / 18;
            this.beginFrequency[1] = begin % 18;
            
            this.endFrequency[0] = end / 18;
            this.endFrequency[1] = end % 18;

            this.total = end - begin;

            this.begin = 0;

            this.averageEnergy = new float[43];
            this.totalEnergy = 0.0f;
            for (int i = 0; i < averageEnergy.Length; i++)
            {
                this.averageEnergy[i] = initialValue;
                this.totalEnergy += this.averageEnergy[i];
            }
        }

        public void ReadFrequencies(float[][] frequency)
        {
            currentEnergy = 0.0f;
            for (int i = beginFrequency[0], j = beginFrequency[1], k = 0; k < total; k++)
            {
                currentEnergy += Math.Abs(frequency[i][j]);
                j = (j + 1) % 18;
                if (j == 0)
                    i++;
            }
            currentEnergy /= total;

            float E = 0.0f;
            E = totalEnergy / 43;

            lastEnergyValue = averageEnergy[begin];
            averageEnergy[begin] = currentEnergy;
            begin = (begin + 1) % averageEnergy.Length;

            totalEnergy = totalEnergy - lastEnergyValue + currentEnergy;

            if (currentEnergy > E * noiseOffset)
            {
                Console.Write("O");
                this.beat = true;
            }
            else
            {
                this.beat = false;
            }
        }

    }
}
